<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="chinese">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">



  
  
    
      
    
    
      
    
  <script src="//cdn.jsdelivr.net/npm/pace-js@1/pace.min.js"></script>
  <link href="//cdn.jsdelivr.net/npm/pace-js@1/themes/blue/pace-theme-minimal.min.css" rel="stylesheet">







<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">










<meta name="description" content="第十一章 持有对象在前面的学习过程中，我们使用的都是固定数量的且生命周期已知的对象。而在一些情况中，我们可能需要不确定数量不确切类型的对象，这种创建一个单一的对象显然是不行的了。Java提供了多种支持，比如数组，数组可以保存一组基本数据类型。但是数组的大小是固定的，在更特殊的编程条件下，固定长度显然是不友好的，所以Java类库提供了一套相当完整的容器类来解决这个问题。我们也称作是集合类。本章优先学">
<meta name="keywords" content="Java Php hexo Thinking in Java">
<meta property="og:type" content="article">
<meta property="og:title" content="Thinking in Java 第十一章">
<meta property="og:url" content="http://yoursite.com/2019/08/07/Thinking-in-Java-第十一章/index.html">
<meta property="og:site_name" content="坚持就是胜利">
<meta property="og:description" content="第十一章 持有对象在前面的学习过程中，我们使用的都是固定数量的且生命周期已知的对象。而在一些情况中，我们可能需要不确定数量不确切类型的对象，这种创建一个单一的对象显然是不行的了。Java提供了多种支持，比如数组，数组可以保存一组基本数据类型。但是数组的大小是固定的，在更特殊的编程条件下，固定长度显然是不友好的，所以Java类库提供了一套相当完整的容器类来解决这个问题。我们也称作是集合类。本章优先学">
<meta property="og:locale" content="chinese">
<meta property="og:updated_time" content="2019-08-10T15:30:47.288Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Thinking in Java 第十一章">
<meta name="twitter:description" content="第十一章 持有对象在前面的学习过程中，我们使用的都是固定数量的且生命周期已知的对象。而在一些情况中，我们可能需要不确定数量不确切类型的对象，这种创建一个单一的对象显然是不行的了。Java提供了多种支持，比如数组，数组可以保存一组基本数据类型。但是数组的大小是固定的，在更特殊的编程条件下，固定长度显然是不友好的，所以Java类库提供了一套相当完整的容器类来解决这个问题。我们也称作是集合类。本章优先学">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":14,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '190coder'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://yoursite.com/2019/08/07/Thinking-in-Java-第十一章/">





  <title>Thinking in Java 第十一章 | 坚持就是胜利</title>
  








</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="chinese">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">坚持就是胜利</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            Categories
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            Archives
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/08/07/Thinking-in-Java-第十一章/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="190coder">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="坚持就是胜利">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">Thinking in Java 第十一章</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-08-07T23:39:57+08:00">
                2019-08-07
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index">
                    <span itemprop="name">Java</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h1 id="第十一章-持有对象"><a href="#第十一章-持有对象" class="headerlink" title="第十一章 持有对象"></a>第十一章 持有对象</h1><p>在前面的学习过程中，我们使用的都是固定数量的且生命周期已知的对象。而在一些情况中，我们可能需要不确定数量不确切类型的对象，这种创建一个单一的对象显然是不行的了。Java提供了多种支持，比如数组，数组可以保存一组基本数据类型。但是数组的大小是固定的，在更特殊的编程条件下，固定长度显然是不友好的，所以Java类库提供了一套相当完整的容器类来解决这个问题。我们也称作是集合类。本章优先学习常用的集合以及用法，后续将会更加深入的讨论其它的集合。</p>
<h2 id="11-1-泛型和类型安全的容器"><a href="#11-1-泛型和类型安全的容器" class="headerlink" title="11.1 泛型和类型安全的容器"></a>11.1 泛型和类型安全的容器</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">class Apple&#123;</span><br><span class="line">	private static long counter;</span><br><span class="line">	private final long id = counter++;</span><br><span class="line">	public long getid()&#123;</span><br><span class="line">		return id;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">class Orange&#123;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br><span class="line">public class AppleAndOrangesWithoutGeneric &#123;</span><br><span class="line">	@SuppressWarnings(&quot;unchecked&quot;)</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		ArrayList al = new ArrayList();</span><br><span class="line">		for(int i=0;i&lt;3;i++)&#123;</span><br><span class="line">			al.add(new Apple());</span><br><span class="line">			al.add(new Orange());</span><br><span class="line">		&#125;</span><br><span class="line">		for(int i=0;i&lt;al.size();i++)&#123;</span><br><span class="line">			Apple apple = (Apple) al.get(i);</span><br><span class="line">			System.out.println(apple.getid());</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在这里我们实际上存入ArrayList是Object对象，因为所有的类都继承自Object类，所以这里实际上不光可以添加Orange对象还可以添加任意类型的对象。我们在get（）获取数据的时候，我们以为获取的是一个Apple对象，实际上获取的是一个Obejct的引用，然后强制转换成我们需要的对象。在这里我们强制的将从ArrayList中取出的Object引用强制转换成Apple类型，那么当遇到这个对象类型实际上是Orange类型时，就会发生类型转换错误。</p>
<p> JavaSE5之后引入了泛型的概念，这个概念应用在这种不确定类型的对象集合中最好不过。例如我们如果想创建一个Apple类型的容器，那么就可以使用ArrayList 其中&lt;&gt;括起来的是类型参数（可以有多个），它指定了这个容器可以保存的数据类型，在进入容器之前就限制了对象的类型，所以在取出数据的时候就不会发生类型转换错误了。相对来说是更加安全的。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">import java.util.ArrayList;</span><br><span class="line"> </span><br><span class="line">class Apple&#123;</span><br><span class="line">	private static long counter;</span><br><span class="line">	private final long id = counter++;</span><br><span class="line">	public long getid()&#123;</span><br><span class="line">		return id;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">class Orange&#123;</span><br><span class="line">	</span><br><span class="line">&#125;</span><br><span class="line">public class AppleAndOrangesWithoutGeneric &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		ArrayList&lt;Apple&gt; al = new ArrayList&lt;Apple&gt;();</span><br><span class="line">		for(int i=0;i&lt;3;i++)&#123;</span><br><span class="line">			al.add(new Apple());</span><br><span class="line">		//	al.add(new Orange());</span><br><span class="line">		&#125;</span><br><span class="line">		for(Apple apple :al)&#123;</span><br><span class="line">			System.out.println(apple.getid());</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>现在你可以阻止将Orange对象加入到Apple容器中了，并且我们可以使用for-each循环获取容器中的内容。实际上当我们固定了一种泛型数据参数，正如前面几章说到的，继承的时候基类收发的消息，子类也可以收发，所以泛型同样支持向上转型，我们可以传递其导出类参数。</p>
<h2 id="11-2-基本概念"><a href="#11-2-基本概念" class="headerlink" title="11.2 基本概念"></a>11.2 基本概念</h2><p> Java容器的用途是“保存对象”，并将其划分为两个不同的概念。</p>
<p>    Collection：一个独立的元素序列，这些元素都服从一条或多条规则。List必须按照插入的顺序保存对象，而Set不能有重复的元素。Queue按照排队的规则来确定对象的产生顺序。</p>
<p>    Map：一组成对的“键值对”对象，允许你使用键来查找值。ArrayList允许你使用数组查找值，所以某种意义上讲它是将对象与数字进行了绑定。</p>
<p>    尽管并非总是这样，但是理想情况下我们都是与这些接口打交道。比如，我们可以像下边这样创建一个List:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;Apple&gt; apples = new ArrayList&lt;Apple&gt;();</span><br></pre></td></tr></table></figure>

<p>ArrayList已经被向上转型为List，使用接口的目的是如何修改它的实现，这里实现由ArrayList完成。这种方式并非永远有效，会带来一个其它的问题，ArrayList类可能新添加了其它的方法，因此当它向上转型为List时，可能会是不完善的。因此如果我们要使用这类方法，那就需要使用更加确切的类型。</p>
<h2 id="11-3-添加一组元素"><a href="#11-3-添加一组元素" class="headerlink" title="11.3 添加一组元素"></a>11.3 添加一组元素</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.Arrays;</span><br><span class="line">import java.util.Collection;</span><br><span class="line">import java.util.Collections;</span><br><span class="line">import java.util.List;</span><br><span class="line"> </span><br><span class="line">public class AddingGroups &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Collection&lt;Integer&gt; collection = new ArrayList&lt;Integer&gt;(Arrays.asList(1,2,3,4,5));</span><br><span class="line">		Integer[] moreInts = &#123;6,7,8,9,10&#125;;</span><br><span class="line">		collection.addAll(Arrays.asList(moreInts));</span><br><span class="line">		Collections.addAll(collection,11,12,13,14);</span><br><span class="line">		Collections.addAll(collection,moreInts);</span><br><span class="line">		List&lt;Integer&gt; list = Arrays.asList(15,16,17,18);</span><br><span class="line">		list.set(1,29);</span><br><span class="line">		//run error 数组不支持变更长度</span><br><span class="line">		list.add(21);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> Collection的构造器可以传递另一个Collection用来初始化，但是这种方式不如定义个空的Collection然后使用addAll的形式添加数据灵活</p>
<h2 id="11-4-容器的打印"><a href="#11-4-容器的打印" class="headerlink" title="11.4 容器的打印"></a>11.4 容器的打印</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.Collection;</span><br><span class="line">import java.util.HashMap;</span><br><span class="line">import java.util.HashSet;</span><br><span class="line">import java.util.LinkedHashMap;</span><br><span class="line">import java.util.LinkedHashSet;</span><br><span class="line">import java.util.LinkedList;</span><br><span class="line">import java.util.Map;</span><br><span class="line">import java.util.TreeMap;</span><br><span class="line">import java.util.TreeSet;</span><br><span class="line">public class PrintingContainers &#123;</span><br><span class="line">	static Collection fill(Collection&lt;String&gt; collection)&#123;</span><br><span class="line">		collection.add(&quot;one&quot;);</span><br><span class="line">		collection.add(&quot;two&quot;);</span><br><span class="line">		collection.add(&quot;three&quot;);</span><br><span class="line">		collection.add(&quot;four&quot;);</span><br><span class="line">		collection.add(&quot;five&quot;);</span><br><span class="line">		collection.add(&quot;five&quot;);</span><br><span class="line">		return collection;</span><br><span class="line">	&#125;</span><br><span class="line">	static Map fill(Map&lt;String,String&gt; map)&#123;</span><br><span class="line">		map.put(&quot;one&quot;,&quot;ONE&quot;);</span><br><span class="line">		map.put(&quot;two&quot;,&quot;TWO&quot;);</span><br><span class="line">		map.put(&quot;three&quot;,&quot;THREE&quot;);</span><br><span class="line">		map.put(&quot;four&quot;,&quot;FOUR&quot;);</span><br><span class="line">		map.put(&quot;five&quot;,&quot;FIVE&quot;);</span><br><span class="line">		map.put(&quot;five&quot;,&quot;FIVE&quot;);</span><br><span class="line">		return map;</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		System.out.println(&quot;ArrayList===&quot; + fill(new ArrayList&lt;String&gt;()));</span><br><span class="line">		System.out.println(&quot;LinkedList===&quot; + fill(new LinkedList&lt;String&gt;()));</span><br><span class="line">		System.out.println(&quot;HashSet===&quot; + fill(new HashSet&lt;String&gt;()));</span><br><span class="line">		System.out.println(&quot;TreeSet===&quot; + fill(new TreeSet&lt;String&gt;()));</span><br><span class="line">		System.out.println(&quot;LinkedHashSet===&quot; + fill(new LinkedHashSet&lt;String&gt;()));</span><br><span class="line">		</span><br><span class="line">		System.out.println(&quot;HashMap===&quot; + fill(new HashMap&lt;String,String&gt;()));</span><br><span class="line">		System.out.println(&quot;TreeMap===&quot; + fill(new TreeMap&lt;String,String&gt;()));</span><br><span class="line">		System.out.println(&quot;LinkedHashMap===&quot; + fill(new LinkedHashMap&lt;String,String&gt;()));</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里展示了Java容器中的两种主要的类型：Collection和Map，Collection又包括List和Set他们每个位置只能保存一个数据。而Map保存数据的形式则是使用键值对“key-value”的形式。List：以特定的顺序保存数据，Set：集合中的元素都不能重复。Collection还包括另外一种Queue，它要求元素只能从集合的一端进入，从另一端取出。<br>    从本例的输出结果可以看出，默认的容器带有的toString方法，可以很好的将容器中的数据展示出来。Collection使用[]括起来，Map使用{}括起来，键值对使用=连接。<br>    接着分析打印输出，ArrayList和LinkedList都是List类型，它们能够按照元素的填入顺序进行打印。区别在于执行某些操作时候的性能不同，而且LinkedList的功能要多于ArrayList，这在后文介绍。<br>    HashSet、TreeSet、LinkedHashSet都是Set类型，每个相同的元素只保存一个，HashSet使用了相当复杂的存储结构，后文会介绍，因此HashSet的存储顺序没有实际意义。TreeSet按元素比较结果的升序排序，LinkedHashSet与List相同，按照元素的插入顺序进行了排序。<br>    Map也可以称作是关联数组，可以使用key查找对应的value，同时可以不用关心它们的大小。Map会自动的扩容。同时也不需要关心打印的顺序。</p>
<h2 id="11-5-List"><a href="#11-5-List" class="headerlink" title="11.5 List"></a>11.5 List</h2><p>List将元素按照插入的顺序排列起来，它在Collection的接口中增加了新的功能，使得可以在List的中间插入和删除元素。List有两种类型如上一节介绍:<br>    1.ArrayList 优势在于随机访问的速度很快，但是在List中间插入和删除元素比较慢。<br>    2.LinkedList 与上基本相反，它的特性集较ArrayList更大。<br>    下面的一个例子展示List的一些特性，首先有个枚举类型，它有几个常量，然后是一个向List中增加数据的方法，这个方法我们使用的是ArrayList，注意前边说到，ArrayList增删操作性能消耗很大，如果我们的程序设计中出现了大量的ArrayList插入操作，那么可能会导致性能的降低</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.List;</span><br><span class="line">import java.util.Random;</span><br><span class="line">enum Pet&#123;</span><br><span class="line">	Pet,Rat,Manx,Mutt,Pug,Cymric,Humaster</span><br><span class="line">&#125;</span><br><span class="line">public class Pets &#123;</span><br><span class="line">	public static List&lt;Pet&gt; arrayList(int n)&#123;</span><br><span class="line">		List&lt;Pet&gt; pets = new ArrayList&lt;Pet&gt;();</span><br><span class="line">		for(int i=0;i&lt;n;i++)&#123;</span><br><span class="line">			Random rand = new Random();</span><br><span class="line">			int j = rand.nextInt(n);</span><br><span class="line">			switch(j)&#123;</span><br><span class="line">			case 0:</span><br><span class="line">				pets.add(Pet.Pet);</span><br><span class="line">				break;</span><br><span class="line">			case 1:</span><br><span class="line">				pets.add(Pet.Rat);</span><br><span class="line">				break;</span><br><span class="line">			case 2:</span><br><span class="line">				pets.add(Pet.Manx);</span><br><span class="line">				break;</span><br><span class="line">			case 3:</span><br><span class="line">				pets.add(Pet.Mutt);</span><br><span class="line">				break;</span><br><span class="line">			case 4:</span><br><span class="line">				pets.add(Pet.Pug);</span><br><span class="line">				break;</span><br><span class="line">			case 5:</span><br><span class="line">				pets.add(Pet.Cymric);</span><br><span class="line">				break;</span><br><span class="line">			case 6:</span><br><span class="line">				pets.add(Pet.Humaster);</span><br><span class="line">				break;</span><br><span class="line">				default:</span><br><span class="line">					break;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		return pets;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="11-6-迭代器"><a href="#11-6-迭代器" class="headerlink" title="11.6 迭代器"></a>11.6 迭代器</h2><p> 迭代器（也是一种设计模式），是一种应用在容器之上的设计。它是一个对象，它的作用是遍历并选择序列中的对象，而不需要确定该序列的底层机构。也就是说，我们使用迭代器的目的是解决了不同容器之间的互通性问题。因此迭代器通常被称作是“轻量级对象”，创建它的代价较小。因此通常有些奇怪的限制。例如：Java中的迭代器只能单向移动，并且它通常：<br>    1、使用方法iterator（）要求容器返回一个Iterator，Iterator将准备好返回容器的第一个元素。<br>    2、使用next（）方法获得容器中的下一个元素。<br>    3、使用hasNext（）方法检查容器中是否还有下一个元素。<br>    4、使用remove（）方法将迭代器中新近返回的元素删除。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">import java.util.Iterator;</span><br><span class="line">import java.util.List;</span><br><span class="line">public class SimpleIterator &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		List&lt;Pet&gt; pets = Pets.arrayList(7);</span><br><span class="line">		Iterator&lt;Pet&gt; it = pets.iterator();</span><br><span class="line">		System.out.println(&quot;1:&quot; + pets);</span><br><span class="line">		System.out.println(&quot;2:&quot; + it);</span><br><span class="line">		while(it.hasNext())&#123;</span><br><span class="line">			Pet p = it.next();</span><br><span class="line">			System.out.println(&quot;---&gt;&quot; + p);</span><br><span class="line">		&#125;</span><br><span class="line">		it = pets.iterator();</span><br><span class="line">		for(int i = 0;i&lt;7;i++)&#123;</span><br><span class="line">			it.next();</span><br><span class="line">			it.remove();</span><br><span class="line">			System.out.println(pets);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>第二行我们打印Iterator时并没有像打印其它对象时把数据打印出来，而是只打印了这个迭代器底层容器的类型ArrayList。还有就是迭代器对象第一次.next之后获取的是第一个元素，remove方法移除的是next方法获取到的元素，所以remove之前必须要调用next方法。在同一方法中使用Iterator时，要注意前面使用过之后，Iterator的位置会发生变化。<br>    现在我们换用其它类型的容器来测试迭代器的作用，这里有个display（）方法，它不考虑任何容器的类型来进行打印：</p>
<p>还有一种比Iterator更加强大的迭代器ListIterator，这个迭代器功能更全，可以向前或者向后移动，也可以使用set（）方法替换它最后访问的元素（使用方式如Iterator的remove方法，要先指定访问元素），同时它还可以使用listIterator（n）方法直接指定到第n个元素的ListIterator。下面的示例展示了ListIterator的功能：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">import java.util.List;</span><br><span class="line">import java.util.ListIterator;</span><br><span class="line">public class SimpleListIterator &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		List&lt;Pet&gt; pets = Pets.arrayList(7);</span><br><span class="line">		ListIterator&lt;Pet&gt; lit = pets.listIterator();</span><br><span class="line">		System.out.println(pets);</span><br><span class="line">		System.out.println(lit);</span><br><span class="line">		System.out.println(&quot;=====Next=====&quot;);</span><br><span class="line">		while(lit.hasNext())&#123;</span><br><span class="line">			int index = lit.nextIndex();</span><br><span class="line">			Pet p = lit.next();</span><br><span class="line">			System.out.println(&quot;Index:&quot; + index + &quot;,&quot; + &quot;Pet:&quot; + p );</span><br><span class="line">		&#125;</span><br><span class="line">		System.out.println(&quot;=====Previous=====&quot;);</span><br><span class="line">		lit = pets.listIterator(7);</span><br><span class="line">		while(lit.hasPrevious())&#123;</span><br><span class="line">			int index = lit.previousIndex();</span><br><span class="line">			Pet p = lit.previous();</span><br><span class="line">			System.out.println(&quot;Index:&quot; + index + &quot;,&quot; + &quot;Pet:&quot; + p );</span><br><span class="line">		&#125;</span><br><span class="line">		System.out.println(&quot;=====Update Set=====&quot;);</span><br><span class="line">		lit = pets.listIterator();</span><br><span class="line">		while(lit.hasNext())&#123;</span><br><span class="line">			Pet p = lit.next();</span><br><span class="line">			lit.set(Pet.Humaster);</span><br><span class="line">		&#125;</span><br><span class="line">		System.out.println(pets);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="11-7-LinkedList"><a href="#11-7-LinkedList" class="headerlink" title="11.7 LinkedList"></a>11.7 LinkedList</h2><p>LinkedList与ArrayList相同都是实现了List接口，但是它在增删的时候效率较高，在随机访问的时候效率略低。LinkedList还增加了其作为栈、队列、双端队列的操作方法。这些方法有的只是名字有差异，或者是返回值有差异。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">import java.util.LinkedList;</span><br><span class="line">public class LinkedListFeatures &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		LinkedList&lt;Pet&gt; pets = new LinkedList&lt;Pet&gt;(Pets.arrayList(7));</span><br><span class="line">		System.out.println(pets);</span><br><span class="line">		//以下两个方法都返回容器的第一个元素 在容器为空的时候抛异常</span><br><span class="line">		System.out.println(&quot;pets.getFirst()---》&quot; + pets.getFirst());</span><br><span class="line">		System.out.println(&quot;pets.elements()---》&quot; + pets.element());</span><br><span class="line">		//与上两个方法相同 区别在于为空时返回null</span><br><span class="line">		System.out.println(&quot;pets.peek()---》&quot; + pets.peek());</span><br><span class="line">		//以下两个方法移除列表的第一个元素 在容器为空的时候抛出异常</span><br><span class="line">		System.out.println(&quot;pets.remove()---&gt;&quot; + pets.remove());</span><br><span class="line">		System.out.println(&quot;pets.removeFirst()---&gt;&quot; + pets.removeFirst());</span><br><span class="line">		//与上两个方法相同 区别在于容器为空时返回null</span><br><span class="line">		System.out.println(&quot;pets.pool()---&gt;&quot; + pets.poll());</span><br><span class="line">		System.out.println(pets);</span><br><span class="line">		//在容器第一个位置加入新的元素 其它元素依次后移</span><br><span class="line">		pets.addFirst(Pet.Manx);</span><br><span class="line">		System.out.println(&quot;After addFirst()&quot; + pets);</span><br><span class="line">		//以下两个方法在容器尾部插入新元素</span><br><span class="line">		pets.add(Pet.Humaster);</span><br><span class="line">		System.out.println(&quot;After add()&quot; + pets);</span><br><span class="line">		pets.addLast(Pet.Pug);</span><br><span class="line">		System.out.println(&quot;After addLast()&quot; + pets);</span><br><span class="line">		//offer 是针对queue 在尾部插入数据 add是针对list 在尾部插入数据</span><br><span class="line">		pets.offer(Pet.Rat);</span><br><span class="line">		System.out.println(&quot;After offer()&quot; + pets);</span><br><span class="line">		//移除最后一个并返回该元素</span><br><span class="line">		System.out.println(&quot;pets.removeLast()&quot; + pets.removeLast());</span><br><span class="line">		System.out.println(&quot;After removeLast()&quot; + pets);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="11-8-Stack-栈"><a href="#11-8-Stack-栈" class="headerlink" title="11.8 Stack 栈"></a>11.8 Stack 栈</h2><p>“栈”通常是指“后进先出的容器”，比如装羽毛球的桶，最后放进去的羽毛球可以第一个被拿出来，因为另一端也就是栈底是封闭的。LinkedList具有能够直接实现栈的所有功能的方法，因此可以直接将LinkedList作为栈使用。这里我们使用一个真正的Stack，内部使用LinkedList来实现它。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">import java.util.LinkedList;</span><br><span class="line">public class Stack&lt;T&gt; &#123;</span><br><span class="line">	private LinkedList&lt;T&gt; storage = new LinkedList&lt;T&gt;();</span><br><span class="line">	public void push(T v)&#123;</span><br><span class="line">		storage.addFirst(v);</span><br><span class="line">	&#125;</span><br><span class="line">	public T peek()&#123;</span><br><span class="line">		return storage.getFirst();</span><br><span class="line">	&#125;</span><br><span class="line">	public T pop()&#123;</span><br><span class="line">		return storage.removeFirst();</span><br><span class="line">	&#125;</span><br><span class="line">	public boolean empty()&#123;</span><br><span class="line">		return storage.isEmpty();</span><br><span class="line">	&#125;</span><br><span class="line">	public String toString()&#123;</span><br><span class="line">		 return storage.toString();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里使用泛型来告诉编译器这个Stack是持有参数化类型T的容器，这个Stack是使用LinkedList实现的，而LinkedList也被告知是使用了T类型的对象。peek（）方法返回栈顶元素，但是并不是移除。而pop（）方法这里是弹出栈顶元素，也就是移除了栈顶元素。如果我们只是需要栈的行为，而不需要其它无关的行为方法，那么这里使用继承就显然不合适了。后边会讨论在Java1.0中，java.util.Stack这个类的设计。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">public class StackTest &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Stack&lt;String&gt; stack = new Stack&lt;String&gt;();</span><br><span class="line">		for(String s : &quot;My Dog has fleas&quot;.split(&quot; &quot;))&#123;</span><br><span class="line">			stack.push(s);</span><br><span class="line">		&#125;</span><br><span class="line">		while(!stack.empty())&#123;</span><br><span class="line">			System.out.print(stack.pop() + &quot; &quot;);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里使用了push方法将字符串“My Dog has fleas”用空格分开的单词压入栈中，然后使用pop方法弹出栈顶元素。因为pop方法调用之后会移除栈顶元素，所以会依次弹出栈中的所有元素。在这里我们使用了自己定义的Stack，如果我们导入了java.util.Stack类的话，那么我们这样使用可能会产生命名冲突的现象，解决方法是我们在实例化的时候使用完整的类名，或者修改我们自己定义的Stack类名。</p>
<h2 id="11-9-Set"><a href="#11-9-Set" class="headerlink" title="11.9 Set"></a>11.9 Set</h2><p> Set不保存重复的元素（至于如何判断元素是否重复，则较为复杂，稍后便会看到），Set最常见的使用是判断对象的归属性，即判断某个对象是否在Set中。正因为如此，Set的查询效率就显得尤为重要了，所以通常会使用HashSet来实现所需要的功能，它对查询专门做了优化。</p>
<p>    Set具有与Collection完全一样的接口，我们可以说Set就是Collection，这是表现了不同的功能，这是Java中继承与多态思想的展现。Set中更加复杂的问题后边17章会介绍。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">import java.util.HashSet;</span><br><span class="line">import java.util.Random;</span><br><span class="line">import java.util.Set;</span><br><span class="line">public class SetofInteger &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Random random = new Random(47);</span><br><span class="line">		Set&lt;Integer&gt; set = new HashSet&lt;Integer&gt;();</span><br><span class="line">		for(int i=0;i&lt;10000;i++)&#123;</span><br><span class="line">			set.add(random.nextInt(30));</span><br><span class="line">		&#125;</span><br><span class="line">		System.out.println(set);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>set中插入了0-29的随机数，插入了10000次，但是从打印结果可以看出，只保证了每个数据只出现了一次。而且似乎插入的顺序并没有规律可寻。这是因为出于查找速度的考虑，HashSet使用了散列，将在17章中介绍。HashSet使用散列存储，TreeSet使用红黑树存储，LinkedHahSet因为查询速度的原因也使用了散列，但是它看起来像是使用了链表来进行存储，因为它保证了元素的插入顺序。</p>
<p>    注意：插入顺序与元素的顺序的区别，插入顺序是我们在容器中添加元素时的顺序，而元素的顺序说的是按照某种规则比如从小到大或者从大到小的顺序，也就是元素的结果。当然，上边的示例如果我们相对元素的结果进行排序，那么可以使用TreeSet来替换，因为LinkedHashSet只是保证了元素的插入顺序。</p>
<p>    Set 常用的方法是使用contains（）判断是否存在某元素，当然还有一些其它的顾名思义的方法：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">import java.util.Collections;</span><br><span class="line">import java.util.HashSet;</span><br><span class="line">import java.util.Set;</span><br><span class="line">public class SetOperations &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Set&lt;String&gt; set1 = new HashSet&lt;String&gt;();</span><br><span class="line">		Collections.addAll(set1,&quot;A B C D E F G H I J K L&quot;.split(&quot; &quot;));</span><br><span class="line">		set1.add(&quot;M&quot;);</span><br><span class="line">		System.out.println(&quot;H:&quot; +  set1.contains(&quot;H&quot;));</span><br><span class="line">		System.out.println(&quot;N:&quot; +  set1.contains(&quot;N&quot;));</span><br><span class="line">		Set&lt;String&gt; set2 = new HashSet&lt;String&gt;();</span><br><span class="line">		Collections.addAll(set2,&quot;H I J K L&quot;.split(&quot; &quot;));</span><br><span class="line">		System.out.println(&quot;set2 in set1:&quot; + set1.containsAll(set2));</span><br><span class="line">		set1.remove(&quot;H&quot;);</span><br><span class="line">		System.out.println(&quot;set1: &quot; + set1);</span><br><span class="line">		System.out.println(&quot;set2 in set1:&quot; + set1.containsAll(set2));</span><br><span class="line">		set1.removeAll(set2);</span><br><span class="line">		System.out.println(&quot;set2 removed from set1:&quot; + set1);</span><br><span class="line">		Collections.addAll(set1,&quot;X Y Z&quot;.split(&quot; &quot;));</span><br><span class="line">		System.out.println(&quot;XYZ added to set1:&quot; + set1);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="11-10-Map"><a href="#11-10-Map" class="headerlink" title="11.10 Map"></a>11.10 Map</h2><p>Map可以将一个对象映射到另一个对象上组建一种一对一的键值关系。比如可以设计这样一个程序来验证Java中Random的随机性，理想情况下，Random对每个随机数产生的概率是相同的。我们测试这一理论，于是定义一个Map，键来表示随机出现的数字，值来表示该数字出现的次数。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">import java.util.HashMap;</span><br><span class="line">import java.util.Map;</span><br><span class="line">import java.util.Random;</span><br><span class="line">public class RandomTest &#123;	</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Random random = new Random(47);</span><br><span class="line">		Map&lt;Integer,Integer&gt; map = new HashMap&lt;Integer,Integer&gt;();</span><br><span class="line">		for(int i =0;i&lt;1000000;i++)&#123;</span><br><span class="line">			int x = random.nextInt(20);</span><br><span class="line">			Integer freq = map.get(x);</span><br><span class="line">			map.put(x,freq == null?1:freq+1);</span><br><span class="line">		&#125;</span><br><span class="line">		System.out.println(map);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p> Map与数组或者其它的Collection一样，可以扩展到多维角度，即key是String类型，value可以重新定义为一个容器。比如上边的示例改造为一个动物有多个名字。那么你需要的就是一个Map&lt;String,List&gt;:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">import java.util.Arrays;</span><br><span class="line">import java.util.HashMap;</span><br><span class="line">import java.util.List;</span><br><span class="line">import java.util.Map;</span><br><span class="line">public class MapOfList &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		 Map&lt;String,List&lt;Pet&gt;&gt; petList = new HashMap&lt;String,List&lt;Pet&gt;&gt;();</span><br><span class="line">		 petList.put(&quot;MyDog&quot;,Arrays.asList(Pet.Cymric,Pet.Humaster,Pet.Mutt));</span><br><span class="line">		 System.out.println(petList);</span><br><span class="line">		 System.out.println(&quot;key:&quot; + petList.keySet());</span><br><span class="line">		 System.out.println(&quot;value:&quot; + petList.values());</span><br><span class="line">		 for(String s:petList.keySet())&#123;</span><br><span class="line">			 System.out.print(s + &quot;:&quot;);</span><br><span class="line">			 for(Pet p:petList.get(s))&#123;</span><br><span class="line">				 System.out.print(p + &quot; &quot;);</span><br><span class="line">			 &#125;</span><br><span class="line">		 &#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="11-11-Queue-队列"><a href="#11-11-Queue-队列" class="headerlink" title="11.11 Queue 队列"></a>11.11 Queue 队列</h2><p>队列是一个典型的先进先出的容器，就像是一个两端打开的管子，从一端放进去的物品，从另一端取出，并且最先取出的是最先放进去的物品。因此队列的取出顺序往往是与插入顺序相同的。正因为队列这种顺序特性，它常常被作为一种可靠的将对象从程序的某个区域发送到另一个区域的途径。LinkedList实现了Queue的接口，因此LinkedList可以当做是Queue的一种实现，这是面向对象编程中继承与多态思想的体现。将LinkedList向上转型为Queue，下面的示例将展示Queue接口中与Queue相关的方法：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">import java.util.LinkedList;</span><br><span class="line">import java.util.Queue;</span><br><span class="line">public class QueueDemo &#123;</span><br><span class="line">	public static void printQ(Queue queue)&#123;</span><br><span class="line">		//不移除的情况下返回队列头部元素  element（）方法相同  peek为空返回null  element为空抛出异常</span><br><span class="line">		while(queue.peek()!=null)&#123;</span><br><span class="line">			//remove（）移除头元素 为空抛出异常 poll 为空返回null</span><br><span class="line">			System.out.println(queue.remove() + &quot; &quot;);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		Queue&lt;Integer&gt; queue = new LinkedList&lt;Integer&gt;();</span><br><span class="line">		for(int i = 0;i&lt;5;i++)&#123;</span><br><span class="line">			//元素插入队尾</span><br><span class="line">			queue.offer(i);</span><br><span class="line">		&#125;</span><br><span class="line">		printQ(queue);</span><br><span class="line">		Queue&lt;Character&gt; qc = new LinkedList&lt;Character&gt;();</span><br><span class="line">		for(char c:&quot;QUEUEDEMO&quot;.toCharArray())&#123;</span><br><span class="line">			qc.offer(c);</span><br><span class="line">		&#125;</span><br><span class="line">		printQ(qc);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;offer方法是队列的相关方法之一，它在队列允许的情况下，将元素插入到队列的尾部，或者返回false，peek和element方法都是在不删除的情况下返回队列的第一个元素，peek在队列为空时返回null，element在队列为空抛NoSuchElementException，poll和remove删除当前队列的第一个元素，如果为空poll返回null，remove抛NoSuchElementException异常。</p>
<p>&emsp;&emsp;先进先出描述了最典型的队列规则，在某些情况下，队列还需要弹出当前最需要的元素，这种队列称作是优先级队列。优先级队列每个元素都具有一个执行的优先级，也就是这个元素何时弹出与何时插入没有必然的联系。PriorityQueue添加到Java SE5中，是为了这种优先级形式自动实现。当我们在PriorityQueue上调用了offer（）方法来插入一个对象时，这个对象在队列中就会被重新排序。默认的排序是对象在队列中的自然顺序。但是你可以通过提供自己的Comparator来修改这个顺序。PriorityQueue可以确保你在调用peek、poll、remove等方法时获取的是当前队列中优先级最高的元素。</p>
<p>&emsp;&emsp;JavaSE5中定义的reverseOrder反序定义了PriorityQueue的优先级。</p>
<h2 id="11-12-Collection和Iterator"><a href="#11-12-Collection和Iterator" class="headerlink" title="11.12 Collection和Iterator"></a>11.12 Collection和Iterator</h2><p>使用Collection和Iterator看起来没有什么区别，通常情况下，使用Collection要更方便一些。</p>
<h2 id="11-13-Foreach与迭代器"><a href="#11-13-Foreach与迭代器" class="headerlink" title="11.13 Foreach与迭代器"></a>11.13 Foreach与迭代器</h2><p>&emsp;&emsp;foreach语法可以应用在数组中，也可以应用在任何Collection对象，之所以能够这样，是因为JavaSE5引入了新的被称为Iterable的接口，该接口包含了一个能够产生Iterator的iterator（）方法，并且Iterable接口被foreach用来在序列中移动。因此如果你创建了任何实现Iterabel的类，都可以将它应用在foreach中。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">import java.util.Iterator;</span><br><span class="line"> </span><br><span class="line">public class IterableClass implements Iterable&lt;String&gt; &#123;</span><br><span class="line">	protected String[] words = (&quot;And that is how we know the earth&quot;).split(&quot; &quot;);</span><br><span class="line">	@Override</span><br><span class="line">	public Iterator&lt;String&gt; iterator() &#123;</span><br><span class="line">		// TODO Auto-generated method stub</span><br><span class="line">		return new Iterator&lt;String&gt;()&#123;</span><br><span class="line">			private int index = 0;</span><br><span class="line">			public boolean hasNext()&#123;</span><br><span class="line">				return index&lt;words.length;</span><br><span class="line">			&#125;</span><br><span class="line">			public String next()&#123;</span><br><span class="line">				return words[index++];</span><br><span class="line">			&#125;</span><br><span class="line">			public void remove()&#123;</span><br><span class="line">				//---</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;;</span><br><span class="line">	&#125;</span><br><span class="line">	</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		for(String s :new IterableClass())&#123;</span><br><span class="line">			System.out.print(s + &quot; &quot;);</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>&emsp;&emsp;iterator（）方法返回的实现了Iterator 的匿名内部类的实例，该匿名内部类可以遍历数组中的所有单词。在main（）中，你可以看到IteratorClass确实可以用于foreach语句中。</p>
<h2 id="11-14-总结"><a href="#11-14-总结" class="headerlink" title="11.14 总结"></a>11.14 总结</h2><p>&emsp;&emsp;容器也就是集合，是Java基础中很重要的一个模块，本篇文章了解了基础的容器使用方式。Java提供了多种容器持有对象的方式：<br>    1.数组将数字也就是下标与内容关联，查询时不需要进行类型转换，缺点是大小一旦确定，则不能被改变。<br>    2.Collection保存单一的元素，Map保存相关联的键值对。<br>    3.像数组一样，List也建立数字索引与对象的关联，因此数组和List都是排序好的容器。<br>    4.如果要进行大量的随机访问，就要使用ArrayList，如果要进行大量的插入删除操作，就要使用LinkedList。<br>    5.各种队列与栈的操作，由LinkedList提供支持。<br>    6.Map是一种将对象与对象进行关联的容器，HashMap设计用来快速访问，TreeMap保持键始终处于排序状态，所以没有HashMap快。LinkedHashMap保持元素插入的顺序，但是也通过散列提供快速访问的能力。<br>    7.Set不接受重复的数据，HashSet提供最快的查询速度，而TreeSet保持元素处于排序状态。LinkedHashSet以插入顺序保持元素。</p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/08/05/Thinking-in-Java-第十章/" rel="next" title="Thinking in Java 第十章">
                <i class="fa fa-chevron-left"></i> Thinking in Java 第十章
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/08/07/Thinking-in-Java-第十二章/" rel="prev" title="Thinking in Java 第十二章">
                Thinking in Java 第十二章 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            Table of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            Overview
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/avatar.jpg" alt="190coder">
            
              <p class="site-author-name" itemprop="name">190coder</p>
              <p class="site-description motion-element" itemprop="description">坚信持续学习就一定能超过大多数人</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/">
              
                  <span class="site-state-item-count">53</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">13</span>
                  <span class="site-state-item-name">categories</span>
                </a>
              </div>
            

            

          </nav>

          

          

          
          

          
          

          <div style>
  <canvas id="canvas" style="width:60%;">当前浏览器不支持canvas，请更换浏览器后再试</canvas>
</div>
<script>
(function(){

   var digit=
    [
        [
            [0,0,1,1,1,0,0],
            [0,1,1,0,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,0,1,1,0],
            [0,0,1,1,1,0,0]
        ],//0
        [
            [0,0,0,1,1,0,0],
            [0,1,1,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [1,1,1,1,1,1,1]
        ],//1
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,0,0,0],
            [0,1,1,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,0,0,0,1,1],
            [1,1,1,1,1,1,1]
        ],//2
        [
            [1,1,1,1,1,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,1,1,0],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//3
        [
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,1,0],
            [0,0,1,1,1,1,0],
            [0,1,1,0,1,1,0],
            [1,1,0,0,1,1,0],
            [1,1,1,1,1,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,1,1]
        ],//4
        [
            [1,1,1,1,1,1,1],
            [1,1,0,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,1,1,1,1,0],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//5
        [
            [0,0,0,0,1,1,0],
            [0,0,1,1,0,0,0],
            [0,1,1,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,0,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//6
        [
            [1,1,1,1,1,1,1],
            [1,1,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0]
        ],//7
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//8
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,1,1,0,0,0,0]
        ],//9
        [
            [0,0,0,0,0,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,0,0,0]
        ]//:
    ];

var canvas = document.getElementById('canvas');

if(canvas.getContext){
    var cxt = canvas.getContext('2d');
    //声明canvas的宽高
    var H = 100,W = 700;
    canvas.height = H;
    canvas.width = W;
    cxt.fillStyle = '#f00';
    cxt.fillRect(10,10,50,50);

    //存储时间数据
    var data = [];
    //存储运动的小球
    var balls = [];
    //设置粒子半径
    var R = canvas.height/20-1;
    (function(){
        var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
        //存储时间数字，由十位小时、个位小时、冒号、十位分钟、个位分钟、冒号、十位秒钟、个位秒钟这7个数字组成
        data.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
    })();

    /*生成点阵数字*/
    function renderDigit(index,num){
        for(var i = 0; i < digit[num].length; i++){
            for(var j = 0; j < digit[num][i].length; j++){
                if(digit[num][i][j] == 1){
                    cxt.beginPath();
                    cxt.arc(14*(R+2)*index + j*2*(R+1)+(R+1),i*2*(R+1)+(R+1),R,0,2*Math.PI);
                    cxt.closePath();
                    cxt.fill();
                }
            }
        }
    }

    /*更新时钟*/
    function updateDigitTime(){
        var changeNumArray = [];
        var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
        var NewData = [];
        NewData.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
        for(var i = data.length-1; i >=0 ; i--){
            //时间发生变化
            if(NewData[i] !== data[i]){
                //将变化的数字值和在data数组中的索引存储在changeNumArray数组中
                changeNumArray.push(i+'_'+(Number(data[i])+1)%10);
            }
        }
        //增加小球
        for(var i = 0; i< changeNumArray.length; i++){
            addBalls.apply(this,changeNumArray[i].split('_'));
        }
        data = NewData.concat();
    }

    /*更新小球状态*/
    function updateBalls(){
        for(var i = 0; i < balls.length; i++){
            balls[i].stepY += balls[i].disY;
            balls[i].x += balls[i].stepX;
            balls[i].y += balls[i].stepY;
            if(balls[i].x > W + R || balls[i].y > H + R){
                balls.splice(i,1);
                i--;
            }
        }
    }

    /*增加要运动的小球*/
    function addBalls(index,num){
        var numArray = [1,2,3];
        var colorArray =  ["#3BE","#09C","#A6C","#93C","#9C0","#690","#FB3","#F80","#F44","#C00"];
        for(var i = 0; i < digit[num].length; i++){
            for(var j = 0; j < digit[num][i].length; j++){
                if(digit[num][i][j] == 1){
                    var ball = {
                        x:14*(R+2)*index + j*2*(R+1)+(R+1),
                        y:i*2*(R+1)+(R+1),
                        stepX:Math.floor(Math.random() * 4 -2),
                        stepY:-2*numArray[Math.floor(Math.random()*numArray.length)],
                        color:colorArray[Math.floor(Math.random()*colorArray.length)],
                        disY:1
                    };
                    balls.push(ball);
                }
            }
        }
    }

    /*渲染*/
    function render(){
        //重置画布宽度，达到清空画布的效果
        canvas.height = 100;
        //渲染时钟
        for(var i = 0; i < data.length; i++){
            renderDigit(i,data[i]);
        }
        //渲染小球
        for(var i = 0; i < balls.length; i++){
            cxt.beginPath();
            cxt.arc(balls[i].x,balls[i].y,R,0,2*Math.PI);
            cxt.fillStyle = balls[i].color;
            cxt.closePath();
            cxt.fill();
        }
    }

    clearInterval(oTimer);
    var oTimer = setInterval(function(){
        //更新时钟
        updateDigitTime();
        //更新小球状态
        updateBalls();
        //渲染
        render();
    },50);
}

})();
</script>



        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#第十一章-持有对象"><span class="nav-number">1.</span> <span class="nav-text">第十一章 持有对象</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#11-1-泛型和类型安全的容器"><span class="nav-number">1.1.</span> <span class="nav-text">11.1 泛型和类型安全的容器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-2-基本概念"><span class="nav-number">1.2.</span> <span class="nav-text">11.2 基本概念</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-3-添加一组元素"><span class="nav-number">1.3.</span> <span class="nav-text">11.3 添加一组元素</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-4-容器的打印"><span class="nav-number">1.4.</span> <span class="nav-text">11.4 容器的打印</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-5-List"><span class="nav-number">1.5.</span> <span class="nav-text">11.5 List</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-6-迭代器"><span class="nav-number">1.6.</span> <span class="nav-text">11.6 迭代器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-7-LinkedList"><span class="nav-number">1.7.</span> <span class="nav-text">11.7 LinkedList</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-8-Stack-栈"><span class="nav-number">1.8.</span> <span class="nav-text">11.8 Stack 栈</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-9-Set"><span class="nav-number">1.9.</span> <span class="nav-text">11.9 Set</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-10-Map"><span class="nav-number">1.10.</span> <span class="nav-text">11.10 Map</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-11-Queue-队列"><span class="nav-number">1.11.</span> <span class="nav-text">11.11 Queue 队列</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-12-Collection和Iterator"><span class="nav-number">1.12.</span> <span class="nav-text">11.12 Collection和Iterator</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-13-Foreach与迭代器"><span class="nav-number">1.13.</span> <span class="nav-text">11.13 Foreach与迭代器</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#11-14-总结"><span class="nav-number">1.14.</span> <span class="nav-text">11.14 总结</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

	
           
         
         <div style>
  <canvas id="canvas" style="width:60%;">当前浏览器不支持canvas，请更换浏览器后再试</canvas>
</div>
<script>
(function(){

   var digit=
    [
        [
            [0,0,1,1,1,0,0],
            [0,1,1,0,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,0,1,1,0],
            [0,0,1,1,1,0,0]
        ],//0
        [
            [0,0,0,1,1,0,0],
            [0,1,1,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [1,1,1,1,1,1,1]
        ],//1
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,0,0,0],
            [0,1,1,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,0,0,0,1,1],
            [1,1,1,1,1,1,1]
        ],//2
        [
            [1,1,1,1,1,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,1,1,0],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//3
        [
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,1,0],
            [0,0,1,1,1,1,0],
            [0,1,1,0,1,1,0],
            [1,1,0,0,1,1,0],
            [1,1,1,1,1,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,1,1]
        ],//4
        [
            [1,1,1,1,1,1,1],
            [1,1,0,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,1,1,1,1,0],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//5
        [
            [0,0,0,0,1,1,0],
            [0,0,1,1,0,0,0],
            [0,1,1,0,0,0,0],
            [1,1,0,0,0,0,0],
            [1,1,0,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//6
        [
            [1,1,1,1,1,1,1],
            [1,1,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,0,0,1,1,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0],
            [0,0,1,1,0,0,0]
        ],//7
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,1,1,0]
        ],//8
        [
            [0,1,1,1,1,1,0],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [1,1,0,0,0,1,1],
            [0,1,1,1,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,0,1,1],
            [0,0,0,0,1,1,0],
            [0,0,0,1,1,0,0],
            [0,1,1,0,0,0,0]
        ],//9
        [
            [0,0,0,0,0,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,1,1,1,0,0],
            [0,0,0,0,0,0,0]
        ]//:
    ];

var canvas = document.getElementById('canvas');

if(canvas.getContext){
    var cxt = canvas.getContext('2d');
    //声明canvas的宽高
    var H = 100,W = 700;
    canvas.height = H;
    canvas.width = W;
    cxt.fillStyle = '#f00';
    cxt.fillRect(10,10,50,50);

    //存储时间数据
    var data = [];
    //存储运动的小球
    var balls = [];
    //设置粒子半径
    var R = canvas.height/20-1;
    (function(){
        var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
        //存储时间数字，由十位小时、个位小时、冒号、十位分钟、个位分钟、冒号、十位秒钟、个位秒钟这7个数字组成
        data.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
    })();

    /*生成点阵数字*/
    function renderDigit(index,num){
        for(var i = 0; i < digit[num].length; i++){
            for(var j = 0; j < digit[num][i].length; j++){
                if(digit[num][i][j] == 1){
                    cxt.beginPath();
                    cxt.arc(14*(R+2)*index + j*2*(R+1)+(R+1),i*2*(R+1)+(R+1),R,0,2*Math.PI);
                    cxt.closePath();
                    cxt.fill();
                }
            }
        }
    }

    /*更新时钟*/
    function updateDigitTime(){
        var changeNumArray = [];
        var temp = /(\d)(\d):(\d)(\d):(\d)(\d)/.exec(new Date());
        var NewData = [];
        NewData.push(temp[1],temp[2],10,temp[3],temp[4],10,temp[5],temp[6]);
        for(var i = data.length-1; i >=0 ; i--){
            //时间发生变化
            if(NewData[i] !== data[i]){
                //将变化的数字值和在data数组中的索引存储在changeNumArray数组中
                changeNumArray.push(i+'_'+(Number(data[i])+1)%10);
            }
        }
        //增加小球
        for(var i = 0; i< changeNumArray.length; i++){
            addBalls.apply(this,changeNumArray[i].split('_'));
        }
        data = NewData.concat();
    }

    /*更新小球状态*/
    function updateBalls(){
        for(var i = 0; i < balls.length; i++){
            balls[i].stepY += balls[i].disY;
            balls[i].x += balls[i].stepX;
            balls[i].y += balls[i].stepY;
            if(balls[i].x > W + R || balls[i].y > H + R){
                balls.splice(i,1);
                i--;
            }
        }
    }

    /*增加要运动的小球*/
    function addBalls(index,num){
        var numArray = [1,2,3];
        var colorArray =  ["#3BE","#09C","#A6C","#93C","#9C0","#690","#FB3","#F80","#F44","#C00"];
        for(var i = 0; i < digit[num].length; i++){
            for(var j = 0; j < digit[num][i].length; j++){
                if(digit[num][i][j] == 1){
                    var ball = {
                        x:14*(R+2)*index + j*2*(R+1)+(R+1),
                        y:i*2*(R+1)+(R+1),
                        stepX:Math.floor(Math.random() * 4 -2),
                        stepY:-2*numArray[Math.floor(Math.random()*numArray.length)],
                        color:colorArray[Math.floor(Math.random()*colorArray.length)],
                        disY:1
                    };
                    balls.push(ball);
                }
            }
        }
    }

    /*渲染*/
    function render(){
        //重置画布宽度，达到清空画布的效果
        canvas.height = 100;
        //渲染时钟
        for(var i = 0; i < data.length; i++){
            renderDigit(i,data[i]);
        }
        //渲染小球
        for(var i = 0; i < balls.length; i++){
            cxt.beginPath();
            cxt.arc(balls[i].x,balls[i].y,R,0,2*Math.PI);
            cxt.fillStyle = balls[i].color;
            cxt.closePath();
            cxt.fill();
        }
    }

    clearInterval(oTimer);
    var oTimer = setInterval(function(){
        //更新时钟
        updateDigitTime();
        //更新小球状态
        updateBalls();
        //渲染
        render();
    },50);
}

})();
</script>



    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">190coder</span>

  
</div>


  <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>





<div>
    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
    <span class="post-meta-divider">|</span>
    <span id="busuanzi_container_site_uv">本站访客数<span id="busuanzi_value_site_uv"></span>人</span>
</div>


        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  


  











  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  

  
  
    <script type="text/javascript" src="//cdn.jsdelivr.net/gh/theme-next/theme-next-canvas-nest@1/canvas-nest.min.js"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
